package net.sansi.v3correctserver.service.analyse;

import lombok.extern.slf4j.Slf4j;
import net.sansi.v3correctserver.entity.IntPoint;
import net.sansi.v3correctserver.entity.screen.CorrectArea;
import net.sansi.v3correctserver.entity.screen.Rect;
import net.sansi.v3correctserver.entity.screen.Screen;
import net.sansi.v3correctserver.util.Matrix;

import java.util.List;

/**
 * Created by Fang
 * create time : 2025/2/19
 * IDE : IntelliJ IDEA
 * <p>
 * 自动分割区域
 */

@Slf4j
public class AutoSplitArea {

    // 默认分割模式
    public static final int MODE_DEFAULT = 0;

    private final Screen screen;
    private final int mode;
    private final int span;
    private final int fCol;
    private final int fRow;
    private final Rect correctRange;

    /**
     * 自动分割区域
     *
     * @param screen       显示屏
     * @param correctRange 矫正范围
     * @param mode         模式
     * @param span         打屏隔点 -1 代表自动评估
     * @param fCol         强制列
     * @param fRow         强制行
     */
    public AutoSplitArea(Screen screen, Rect correctRange, int mode, int span, int fCol, int fRow) {
        this.screen = screen;
        this.mode = mode;
        this.span = span;
        this.fCol = fCol;
        this.fRow = fRow;
        this.correctRange = correctRange;
    }

    /**
     * 自动分割区域
     *
     * @return 分割后的区域列表
     */
    public List<CorrectArea> autoSplitArea() {
        int[] splits = new int[]{fCol, fRow};
        if (splits[0] <= 0 || splits[1] <= 0) {
            splits = computeColRow();
        }
        log.info("分割行列为：[列] {}, [行] {} [数量] {}", splits[0], splits[1], splits[0] * splits[1]);
        return split2Area(splits[0], splits[1]);
    }

    /**
     * 根据分割点分割区域
     *
     * @param col 列数
     * @param row 行数
     * @return 区域列表
     */
    public List<CorrectArea> split2Area(int col, int row) {
        int sw = correctRange.getWidth(), sh = correctRange.getHeight();
        int remCol = sw % col, remRow = sh % row;
        int colWidth = sw / col, rowHeight = sh / row;
        Matrix<CorrectArea> areas = new Matrix<>(col, row);
        int sx = correctRange.getLeft(), sy = correctRange.getTop();
        for (int x = 0; x < col; x++) {
            for (int y = 0; y < row; y++) {
                int cw = colWidth + (x < remCol ? 1 : 0);
                int rw = rowHeight + (y < remRow ? 1 : 0);
                CorrectArea area = new CorrectArea();
                area.setAreaId(x * row + y);
                int startX = x != 0 ? areas.get(x - 1, y).getValidArea().getRight() + 1 : sx;
                int startY = y - 1 > -1 ? areas.get(x, y - 1).getValidArea().getBottom() + 1 : sy;
                area.setValidArea(
                        new Rect(cw, rw, new IntPoint(startX, startY))
                );
                areas.set(x, y, area);
            }
        }

        return areas.toListStartCenter();
    }

    /**
     * 将屏幕分成多少个行列
     *
     * @return [列， 行]
     */
    private int[] computeColRow() {
        int sw = correctRange.getWidth(), sh = correctRange.getHeight();
        int[] niceWH = evaluateNiceWH();
        int span = evaluateSpan();
        int niceW = niceWH[0] * span, niceH = niceWH[1] * span;
        double niceRatio = evaluateNiceWHRatio();
        int scRatio = sw / sh;
        if (scRatio > niceRatio && fCol == -1 || fRow != -1) {
            sw = screen.getHeight();
            sh = screen.getWidth();
            niceW = niceWH[1] * span;
            niceH = niceWH[0] * span;
        }
        int col = (int) Math.round(sw * 1.0 / niceW);
        col = Math.max(col, 1);
        int max = Math.max(fCol, fRow);
        if (max != -1) col = max;
        int tNiceH = (int) Math.round(sw * 1.0 / col * niceH / niceW);
        int groupH = Math.max(tNiceH, niceH);
        int row = (int) Math.round(sh * 1.0 / groupH);
        row = Math.max(row, 1);
        if (scRatio > niceRatio) return new int[]{row, col};
        return new int[]{col, row};
    }

    /**
     * 评估隔点数量
     *
     * @return 隔点数量
     */
    public int evaluateSpan() {
        if (span > 0) return span;
        return 4;
    }

    /**
     * 评估最佳 宽高比
     *
     * @return 高宽比
     */
    public double evaluateNiceWHRatio() {
        return 400 / 300.0;
    }

    /**
     * 评估最佳宽高
     *
     * @return 宽高
     */
    public int[] evaluateNiceWH() {
        double ratio = evaluateNiceWHRatio();
        int w = 160;
        int h = (int) (w / ratio);
        return new int[]{w, h};
    }

}
